package com.cjx.stars.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjx.stars.common.MyException;
import com.cjx.stars.common.Response;
import com.cjx.stars.common.ResponseUtils;
import com.cjx.stars.constant.MessageTypeEnum;
import com.cjx.stars.mapper.BlogLikeMapper;
import com.cjx.stars.mapper.BlogMapper;
import com.cjx.stars.pojo.request.BlogUpdateRequest;
import com.cjx.stars.pojo.table.Blog;
import com.cjx.stars.pojo.table.BlogLike;
import com.cjx.stars.pojo.table.Message;
import com.cjx.stars.service.BlogLikeService;
import com.cjx.stars.service.BlogService;
import com.cjx.stars.service.MessageService;
import com.cjx.stars.utils.RegexValidationUtils;
import com.cjx.stars.utils.UserHolder;
import lombok.Data;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.time.LocalDateTime;

import static com.cjx.stars.constant.FailMessage.FAILED_TO_LIKE;
import static com.cjx.stars.constant.FailMessage.PARAMETER_ABNORMAL;
import static com.cjx.stars.constant.RedisConstant.BLOG_LIKED_KEY;
import static com.cjx.stars.constant.RedisConstant.MESSAGE_LIKE_NUM_KEY;

/**
* @author cjx
* @description 针对表【blog_like】的数据库操作Service实现
* @createDate 2024-04-04 16:28:36
*/
@Service
public class BlogLikeServiceImpl extends ServiceImpl<BlogLikeMapper, BlogLike>
    implements BlogLikeService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private BlogService blogService;
    @Resource
    private BlogLikeMapper blogLikeMapper;
    @Resource
    private MessageService messageService;

    @Override
    @Transactional
    public Response<?> addBlogLike(Long blogId) {
        // 1.获取登录用户
        Long userId = Long.valueOf(UserHolder.getUser().getUserId());
        // 2.判断当前登录用户是否已经点赞
        String key = BLOG_LIKED_KEY + blogId;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        Blog blog = blogService.getById(blogId);
        if (BooleanUtil.isFalse(isMember)) {
            //3.如果未点赞，可以点赞
            //3.1 数据库点赞数+1
            boolean isSuccess = blogService.update().setSql("liked_num = liked_num + 1").eq("id", blogId).update();
            //保存数据到博文点赞关系表 -
            //判断之前是否有点赞，如果有点赞记录，则恢复点赞记录
            BlogLike oldBlogLike = blogLikeMapper.getIsLike(blogId,userId);
            if (oldBlogLike != null){
                oldBlogLike.setIsDelete(0);
                oldBlogLike.setUpdateTime(DateTime.now());
               blogLikeMapper.updateDeleteLike(blogId,userId);
            }else {
                //没有过点赞记录，创建一个
                BlogLike blogLike = new BlogLike();
                blogLike.setBlogId(blogId);
                blogLike.setUserId(userId);
                boolean save = save(blogLike);
                if (BooleanUtil.isFalse(save)||BooleanUtil.isFalse(isSuccess)){
                    throw new MyException(FAILED_TO_LIKE);
                }
            }
            //3.2 保存用户到Redis的set集合
            if (isSuccess ) {
                stringRedisTemplate.opsForSet().add(key, userId.toString());
            }
            //存入点赞消息信息，将点赞对象的点赞数量+1
            Message message = new Message();
            message.setType(MessageTypeEnum.BLOG_LIKE.getValue());
            message.setFromId(userId);
            message.setToId(blog.getUserId());
            message.setData(String.valueOf(blogId));
            messageService.save(message);
            //查询点赞数量redis信息并做处理
            String likeNumKey = MESSAGE_LIKE_NUM_KEY + blog.getUserId();
            Boolean hasKey = stringRedisTemplate.hasKey(likeNumKey);
            if (Boolean.TRUE.equals(hasKey)) {
                stringRedisTemplate.opsForValue().increment(likeNumKey);
            } else {
                stringRedisTemplate.opsForValue().set(likeNumKey, "1");
            }
        } else {
            //4.如果已点赞，取消点赞
            //4.1 数据库点赞数-1
            boolean isSuccess = blogService.update().setSql("liked_num = liked_num - 1").eq("id", blogId).update();
            //删除该点赞关系
            remove(new LambdaQueryWrapper<BlogLike>().eq(BlogLike::getBlogId, blogId).eq(BlogLike::getUserId, userId));
            //4.2 把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForSet().remove(key, userId.toString());
            }
            //删除点赞消息信息
            messageService.remove(new LambdaQueryWrapper<Message>()
                    .eq(Message::getType, MessageTypeEnum.BLOG_LIKE.getValue())
                    .eq(Message::getFromId, userId)
                    .eq(Message::getToId, blog.getUserId())
                    .eq(Message::getData, String.valueOf(blog.getId())));
            //被点赞用户的消息数量-1
            String likeNumKey = MESSAGE_LIKE_NUM_KEY + blog.getUserId();
            String upNumStr = stringRedisTemplate.opsForValue().get(likeNumKey);
            if (!StrUtil.isNullOrUndefined(upNumStr) && Long.parseLong(upNumStr) != 0) {
                stringRedisTemplate.opsForValue().decrement(likeNumKey);
            }
        }
            return ResponseUtils.success();
    }






}




